#include "Color.h"
#include <trax.hpp>

namespace AtomTrace{

    const Color Color::WHITE(1.0f, 1.0f, 1.0f);
    const Color Color::BLACK(0.0f, 0.0f, 0.0f);

    Color::Color() 
    {
      R = 1.f;
      G = 1.f;
      B = 1.f;
    }

    Color::Color(const Color& copy) 
    {
      R = copy.R;
      G = copy.G;
      B = copy.B;
    }
    
    Color::Color(float r, float g, float b)
    {
        R = r;
        G = g;
        B = b;
    }
    
    Color::Color(float intens) :
        R(intens),
        G(intens),
        B(intens)
    {}

    Color& Color::operator=(const Color& copy)
    {
      R = copy.R;
      G = copy.G;
      B = copy.B;
      return *this;
    }

    Color& Color::operator=(const float val)
    {
    	R=G=B=val;
    	return *this;
    }

    const Color & Color::LoadFromGM(int addr)
    {
        R = loadf(addr, 0);
        G = loadf(addr, 1);
        B = loadf(addr, 2);
        return *this;
    }

    void Color::SaveToGM(int addr)
    {
    	storef(R, addr, 0);
    	storef(G, addr, 1);
    	storef(B, addr, 2);
    }
    
    void Color::SaveToGM(int addr) const
    {
    	storef(R, addr, 0);
    	storef(G, addr, 1);
    	storef(B, addr, 2);
    }

    float Color::r() const 
    {
      return R;
    }
    float Color::g() const 
    {
      return G;
    }
    float Color::b() const 
    {
      return B;
    }

    const Color Color::operator*(const Color & other) const
    {
        Color result;
        result.R = this->R * other.R;
        result.G = this->G * other.G;
        result.B = this->B * other.B;
        return result;
    }

    const Color Color::operator*(float scalar) const
    {
        Color result;
        result.R = this->R * scalar;
        result.G = this->G * scalar;
        result.B = this->B * scalar;
        return result;
    }
    
    const Color & Color::operator*=(const Color & other)
    {
        //printf("Color*=(Color) call\n");
        this->R *= other.R;
        this->G *= other.G;
        this->B *= other.B;
        return *this;
    }
    
    const Color & Color::operator*=(float scalar)
    {
        R *= scalar;
        G *= scalar;
        B *= scalar;
        return *this;
    }

    const Color Color::operator/(float s) const
    {
    	Color res;
    	res.R = R / s;
    	res.G = G / s;
    	res.B = B / s;
    	return res;
    }

    const Color & Color::operator/=(float s)
	{
    	R /= s;
    	G /= s;
    	B /= s;
    	return *this;
	}

    const Color Color::operator+(const Color & other) const
    {
        Color res;
        res.R = R+other.R;
        res.G = G+other.G;
        res.B = B+other.B;
        return res;
    }

    const Color Color::operator-(const Color & other) const
    {
        Color res;
        res.R = R-other.R;
        res.G = G-other.G;
        res.B = B-other.B;
        return res;
    }

    const Color & Color::operator+=(const Color & other)
    {
        R += other.R;
        G += other.G;
        B += other.B;
        return *this;
    }

    void Color::Clamp(float cmin, float cmax)
    {
        float *pval = &R;
        for(int i=0; i<3; i++)
        {
            if(*pval > cmax) *pval = cmax;
            if(*pval < cmin) *pval = cmin;
            pval++;
        }
    }

}// namespace AtomTrace

